import axios from 'axios'
import { Loading } from 'element-ui'
import router from '@/router'

// ajax统一配置
const instance = axios.create({
  method: 'get',
  baseURL: '',
  timeout: 180000,
  responseType: 'json',
})

const handleWithParameter = function (
  url,
  {
    method = 'GET',
    contentType = 'application/json; charset=UTF-8',
    params = {},
    data = {},
    config = {},
    customUrlParams = '',
    responseType,
  }
) {
  const { headers } = instance.defaults
  const token = sessionStorage.getItem('GdToken')
  const branchId = sessionStorage.getItem('branchId')
  instance.defaults.headers = {
    ...headers,
    'Content-Type': contentType,
    'branch-id': branchId || '',
    token: token ? `${token}` : ''
  }

  if (responseType) {
    instance.defaults.responseType = responseType
  } else {
    instance.defaults.responseType = 'json'
  }
  // url替换参数
  let urlNew = url
  const paramsNew = { ...params }

  /*eslint-disable*/
  for (const key in params) {
    const reg = new RegExp(`:${key}`, "g");
    if ({}.hasOwnProperty.call(params, key) && reg.test(urlNew)) {
      urlNew = urlNew.replace(reg, params[key]);
      delete paramsNew[key];
    }
  }

  switch (method.toLowerCase()) {
    case "get":
      return instance.get(urlNew, { params: paramsNew, ...config });
    case "delete":
      return instance.delete(urlNew, { params: paramsNew });
    case "post":
      return instance.post(`${urlNew}${customUrlParams}`, data, config);
    case "patch":
      return instance.patch(urlNew, data, config);
    case "put":
      return instance.put(urlNew, data);
    default: {
      const res = {
        then: (resolve) =>
          resolve({
            code: 300,
            msg: "method方式错误",
          }),
      };
      return Promise.resolve(res);
    }
  }
};

/*
 * pre: ajax提交前
 * success: ajax连接成功返回正确结果后
 * error: ajax连接成功返回错误结果后
 * fail: ajax连接失败（网络错误）
 * always: ajax无论成功与失败都要执行
 */
const suffix = ["pre", "success", "error", "fail", "always"];

let loadingCnt = 0;
let noLoading = true;
let loadingInstance = null;

const createActions = function (actionMap) {
  const eventNames = Object.keys(actionMap);
  const fnsMap = {};
  eventNames.forEach((eventName) => {
    const configOrFn = actionMap[eventName];
    if (typeof configOrFn !== "function") {
      const config = { showError: true, ...configOrFn };
      fnsMap[eventName] = ({ commit }, payload = {}) => {
        const handleRoot = { root: false };
        const showLoading =
          config.hasLoading || config.hasLoading === undefined;
        // console.log({ showLoading })
        if (showLoading) {
          loadingCnt++;
          if (noLoading) {
            noLoading = false;
            loadingInstance = Loading.service({
              lock: true,
              text: "数据请求中…",
              spinner: "el-icon-loading",
            });
          }
        }
        if (config.actionType) {
          commit(`${config.actionType}_PRE`, payload, handleRoot);
        }

        return handleWithParameter(config.url, {
          ...payload,
          ...config,
        })
          .then((res) => {
            const { code, message } = res.data;
            const params =
              res.config.params === undefined
                ? res.config.data
                : res.config.params;

            let dataRes = {};
            // 是否需要接口传递的参数
            if (config.needFormData) {
              dataRes = { data: res };
            } else {
              dataRes =
                res.data.data === undefined
                  ? {
                      ...res.data,
                      data:
                        typeof params === "string"
                          ? JSON.parse(params)
                          : params,
                    }
                  : res.data;
            }

            if (res.headers["content-disposition"]) {
              return {
                data: res.data,
                contentDisposition: res.headers["content-disposition"],
              };
            }
            // always只有在成功时才返回数据，非200或异常都不返回数据
            if (code === 200) {
              if (config.actionType) {
                commit(
                  `${config.actionType}_SUCCESS`,
                  dataRes.data,
                  handleRoot
                );
                commit(`${config.actionType}_ALWAYS`, dataRes.data, handleRoot);
              }
              return res.data;
            } else if (code === 401){
              localStorage.clear()
              router.push('/login')
            } else {
              if (config.actionType) {
                commit(`${config.actionType}_ERROR`, message, handleRoot);
                commit(`${config.actionType}_ALWAYS`, null, handleRoot);
              }
              if (message && !config.notShow) {
                window.projectApp.$message({
                  message,
                  type: "error",
                });
              }
              return res.data;
            }
          })
          .catch((error) => {
            if (error.response && config.showError) {
              let message = "";
              if ( error.response.status === 401) {
                localStorage.clear()
                router.push({name: 'Login'})
              } else {
                message = `请稍后重试! ${error.response.status}`;
              }
              if (config.actionType) {
                commit(`${config.actionType}_FAIL`, null, handleRoot);
                commit(`${config.actionType}_ALWAYS`, null, handleRoot);
              }
              if (message) {
                window.projectApp.$message({
                  message,
                  type: "error",
                });
              }
            } else {
              if (config.showErrorStack) {
                window.projectApp.$message({
                  message: `${error.message}！${error.stack}!`,
                  // message: '数据量过大，30秒内未返回数据!',
                  type: "error",
                });
              }
            }
          })
          .finally(() => {
            // console.log(showLoading, 'showLoading');
            if (showLoading) {
              loadingCnt--;
            }
            // console.log(loadingCnt, 'loadingCnt');
            if (loadingCnt <= 0) {
              loadingInstance?.close();
              noLoading = true;
            }
          });
      };
    } else {
      fnsMap[eventName] = configOrFn;
    }
  });
  return fnsMap;
};

const handleMutations = function (mutationsMap) {
  const result = { ...mutationsMap };
  Object.keys(result).forEach((actionType) => {
    const fnOrObject = result[actionType];
    if (fnOrObject && typeof fnOrObject !== "function") {
      delete result[actionType];
      const keys = Object.keys(fnOrObject);
      // 补充没有的默认配置
      suffix.forEach((str) => {
        if (!keys.includes(str)) {
          keys.push(str);
          fnOrObject[str] = () => {};
        }
      });

      keys.forEach((suffixAction) => {
        result[`${actionType}_${suffixAction.toUpperCase()}`] =
          fnOrObject[suffixAction];
      });
    }
  });

  return result;
};

export { createActions, handleMutations };
